/*     */ package com.zimbra.cs.imap;
/*     */ 
/*     */ import com.google.common.base.Objects;
/*     */ import com.google.common.base.Objects.ToStringHelper;
/*     */ import com.zimbra.common.mime.ContentDisposition;
/*     */ import com.zimbra.common.mime.ContentType;
/*     */ import com.zimbra.common.mime.MimeCompoundHeader;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.ArrayUtil;
/*     */ import com.zimbra.common.util.ByteUtil;
/*     */ import com.zimbra.common.util.Pair;
/*     */ import com.zimbra.cs.mailbox.Contact;
/*     */ import com.zimbra.cs.mailbox.Flag;
/*     */ import com.zimbra.cs.mailbox.MailItem;
/*     */ import com.zimbra.cs.mailbox.MailItem.Type;
/*     */ import com.zimbra.cs.mailbox.Message;
/*     */ import com.zimbra.cs.mailbox.util.TagUtil;
/*     */ import com.zimbra.cs.mime.MPartInfo;
/*     */ import com.zimbra.cs.mime.Mime;
/*     */ import com.zimbra.cs.mime.Mime.FixedMimeMessage;
/*     */ import com.zimbra.cs.service.formatter.VCard;
/*     */ import com.zimbra.cs.util.JMSession;
/*     */ import java.io.ByteArrayOutputStream;
/*     */ import java.io.IOException;
/*     */ import java.io.InputStream;
/*     */ import java.io.PrintStream;
/*     */ import java.io.Serializable;
/*     */ import java.io.UnsupportedEncodingException;
/*     */ import java.text.DateFormat;
/*     */ import java.text.SimpleDateFormat;
/*     */ import java.util.Collection;
/*     */ import java.util.Comparator;
/*     */ import java.util.Date;
/*     */ import java.util.EnumSet;
/*     */ import java.util.Iterator;
/*     */ import java.util.LinkedList;
/*     */ import java.util.List;
/*     */ import java.util.Locale;
/*     */ import java.util.Map.Entry;
/*     */ import java.util.Set;
/*     */ import java.util.TimeZone;
/*     */ import java.util.TreeSet;
/*     */ import javax.mail.MessagingException;
/*     */ import javax.mail.internet.InternetAddress;
/*     */ import javax.mail.internet.MimeBodyPart;
/*     */ import javax.mail.internet.MimeMessage;
/*     */ import javax.mail.internet.MimePart;
/*     */ import javax.mail.internet.ParseException;
/*     */ import javax.mail.util.SharedByteArrayInputStream;
/*     */ import org.apache.commons.codec.EncoderException;
/*     */ import org.apache.commons.codec.net.BCodec;
/*     */ import org.apache.commons.codec.net.QCodec;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class ImapMessage
/*     */   implements Comparable<ImapMessage>, Serializable
/*     */ {
/*     */   private static final long serialVersionUID = -1756550148606322493L;
/*     */   
/*     */   static class ImapMessageSet
/*     */     extends TreeSet<ImapMessage>
/*     */   {
/*     */     private static final long serialVersionUID = 4831178352505203361L;
/*     */     
/*     */     ImapMessageSet()
/*     */     {
/*  80 */       super();
/*     */     }
/*     */     
/*     */     ImapMessageSet(Collection<ImapMessage> msgs) {
/*  84 */       this();
/*  85 */       addAll(msgs);
/*     */     }
/*     */   }
/*     */   
/*  89 */   public static final Set<MailItem.Type> SUPPORTED_TYPES = EnumSet.of(MailItem.Type.MESSAGE, MailItem.Type.CHAT, MailItem.Type.CONTACT);
/*     */   
/*     */ 
/*  92 */   static final int IMAP_FLAGS = Flag.BITMASK_UNREAD | Flag.BITMASK_FLAGGED | Flag.BITMASK_DELETED | Flag.BITMASK_DRAFT | Flag.BITMASK_REPLIED | Flag.BITMASK_FORWARDED | Flag.BITMASK_NOTIFIED;
/*     */   
/*     */   static final short FLAG_RECENT = 1;
/*     */   
/*     */   static final short FLAG_SPAM = 2;
/*     */   
/*     */   static final short FLAG_NONSPAM = 4;
/*     */   
/*     */   static final short FLAG_JUNKRECORDED = 8;
/*     */   
/*     */   static final short FLAG_IS_CONTACT = 16;
/*     */   
/*     */   static final short FLAG_ADDED = 256;
/*     */   static final short FLAG_EXPUNGED = 512;
/*     */   static final short MUTABLE_SESSION_FLAGS = 14;
/*     */   static final short SESSION_FLAGS = 799;
/*     */   int sequence;
/*     */   int msgId;
/*     */   int imapUid;
/*     */   short sflags;
/*     */   int flags;
/*     */   String[] tags;
/*     */   
/*     */   public ImapMessage(int id, MailItem.Type type, int imapId, int flags, String[] tags)
/*     */   {
/* 117 */     this.msgId = id;
/* 118 */     this.imapUid = imapId;
/* 119 */     this.sflags = (type == MailItem.Type.CONTACT ? 16 : 0);
/* 120 */     this.flags = (flags & IMAP_FLAGS);
/* 121 */     this.tags = tags;
/*     */   }
/*     */   
/*     */   public ImapMessage(MailItem item) {
/* 125 */     this(item.getId(), item.getType(), item.getImapUid(), item.getFlagBitmask(), item.getTags());
/*     */   }
/*     */   
/*     */   ImapMessage(ImapMessage i4msg) {
/* 129 */     this.msgId = i4msg.msgId;
/* 130 */     this.imapUid = i4msg.imapUid;
/* 131 */     this.sflags = ((short)(i4msg.sflags & 0x10));
/* 132 */     this.flags = i4msg.flags;
/* 133 */     this.tags = i4msg.tags;
/*     */   }
/*     */   
/*     */   ImapMessage reset() {
/* 137 */     this.sflags = ((short)(this.sflags & 0x10));
/* 138 */     return this;
/*     */   }
/*     */   
/*     */   MailItem.Type getType() {
/* 142 */     return (this.sflags & 0x10) == 0 ? MailItem.Type.MESSAGE : MailItem.Type.CONTACT;
/*     */   }
/*     */   
/*     */   boolean isTagged(ImapFlagCache.ImapFlag i4flag) {
/* 146 */     return i4flag == null ? false : i4flag.matches(this);
/*     */   }
/*     */   
/*     */   boolean isExpunged() {
/* 150 */     return (this.sflags & 0x200) != 0;
/*     */   }
/*     */   
/*     */   boolean isAdded() {
/* 154 */     return (this.sflags & 0x100) != 0;
/*     */   }
/*     */   
/*     */   ImapMessage setExpunged(boolean expunged) {
/* 158 */     this.sflags = ((short)(expunged ? this.sflags | 0x200 : this.sflags & 0xFDFF));
/* 159 */     return this;
/*     */   }
/*     */   
/*     */   ImapMessage setAdded(boolean added) {
/* 163 */     this.sflags = ((short)(added ? this.sflags | 0x100 : this.sflags & 0xFEFF));
/* 164 */     return this;
/*     */   }
/*     */   
/*     */   long getSize(MailItem item) throws ServiceException {
/* 168 */     if ((item instanceof Message)) {
/* 169 */       return item.getSize();
/*     */     }
/*     */     
/* 172 */     return ((Long)getContent(item).getFirst()).longValue();
/*     */   }
/*     */   
/*     */ 
/*     */   public int compareTo(ImapMessage i4msg)
/*     */   {
/* 178 */     if (this.imapUid == i4msg.imapUid) {
/* 179 */       return 0;
/*     */     }
/* 181 */     return this.imapUid < i4msg.imapUid ? -1 : 1;
/*     */   }
/*     */   
/*     */   public boolean equals(Object o)
/*     */   {
/* 186 */     return ((o instanceof ImapMessage)) && (this.msgId == ((ImapMessage)o).msgId);
/*     */   }
/*     */   
/*     */   public int hashCode()
/*     */   {
/* 191 */     return this.msgId;
/*     */   }
/*     */   
/*     */   static class SequenceComparator implements Comparator<ImapMessage>
/*     */   {
/*     */     public int compare(ImapMessage o1, ImapMessage o2) {
/* 197 */       if (o1 == null)
/* 198 */         return o2 == null ? 0 : -1;
/* 199 */       if (o2 == null) {
/* 200 */         return 1;
/*     */       }
/* 202 */       return o1.sequence == o2.sequence ? 0 : o1.sequence < o2.sequence ? -1 : 1;
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/* 208 */   private static final DateFormat GMT_DATE_FORMAT = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z (z)", Locale.US);
/*     */   
/* 210 */   static { GMT_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT")); }
/*     */   
/*     */ 
/* 213 */   static final Pair<Long, InputStream> EMPTY_CONTENT = new Pair(Long.valueOf(0L), new SharedByteArrayInputStream(new byte[0]));
/*     */   private static final String NO_FLAGS = "FLAGS ()";
/*     */   
/* 216 */   static Pair<Long, InputStream> getContent(MailItem item) throws ServiceException { if ((item instanceof Message))
/* 217 */       return new Pair(Long.valueOf(item.getSize()), item.getContentStream());
/* 218 */     if ((item instanceof Contact)) {
/*     */       try {
/* 220 */         VCard vcard = VCard.formatContact((Contact)item);
/* 221 */         QCodec qcodec = new QCodec();qcodec.setEncodeBlanks(true);
/* 222 */         StringBuilder header = new StringBuilder();
/* 223 */         header.append("Subject: ").append(qcodec.encode(vcard.fn, "utf-8")).append(ImapHandler.LINE_SEPARATOR);
/* 224 */         synchronized (GMT_DATE_FORMAT) {
/* 225 */           header.append("Date: ").append(GMT_DATE_FORMAT.format(new Date(item.getDate()))).append(ImapHandler.LINE_SEPARATOR);
/*     */         }
/* 227 */         header.append("Content-Type: text/x-vcard; charset=\"utf-8\"").append(ImapHandler.LINE_SEPARATOR);
/* 228 */         header.append("Content-Transfer-Encoding: 8bit").append(ImapHandler.LINE_SEPARATOR);
/*     */         
/* 230 */         ByteArrayOutputStream baos = new ByteArrayOutputStream();
/* 231 */         baos.write(header.toString().getBytes("us-ascii"));
/* 232 */         baos.write(ImapHandler.LINE_SEPARATOR_BYTES);
/* 233 */         baos.write(vcard.getFormatted().getBytes("utf-8"));
/* 234 */         return new Pair(Long.valueOf(baos.size()), new SharedByteArrayInputStream(baos.toByteArray()));
/*     */       } catch (Exception e) {
/* 236 */         throw ServiceException.FAILURE("problems serializing contact " + item.getId(), e);
/*     */       }
/*     */     }
/* 239 */     return EMPTY_CONTENT;
/*     */   }
/*     */   
/*     */   static MimeMessage getMimeMessage(MailItem item) throws ServiceException
/*     */   {
/* 244 */     if ((item instanceof Message)) {
/* 245 */       return ((Message)item).getMimeMessage(false);
/*     */     }
/*     */     
/* 248 */     InputStream is = (InputStream)getContent(item).getSecond();
/*     */     try {
/* 250 */       return new Mime.FixedMimeMessage(JMSession.getSession(), is);
/*     */     } catch (MessagingException e) {
/* 252 */       throw ServiceException.FAILURE("error creating MimeMessage for " + item.getType() + ' ' + item.getId(), e);
/*     */     } finally {
/* 254 */       ByteUtil.closeStream(is);
/*     */     }
/*     */   }
/*     */   
/*     */   int getModseq(MailItem item) {
/* 259 */     return item.getModifiedSequence();
/*     */   }
/*     */   
/*     */   void setPermanentFlags(int f, String[] t, int changeId, ImapFolder parent) {
/* 263 */     if ((TagUtil.tagsMatch(t, this.tags)) && ((f & IMAP_FLAGS) == (this.flags & IMAP_FLAGS))) {
/* 264 */       return;
/*     */     }
/* 266 */     this.flags = (f & IMAP_FLAGS);
/* 267 */     this.tags = t;
/* 268 */     if (parent != null) {
/* 269 */       parent.updateTagCache(this);
/* 270 */       parent.dirtyMessage(this, changeId);
/*     */     }
/*     */   }
/*     */   
/*     */   void setSessionFlags(short s, ImapFolder parent) {
/* 275 */     if ((s & 0xE) == (this.sflags & 0xE)) {
/* 276 */       return;
/*     */     }
/* 278 */     this.sflags = ((short)(s & 0xE | this.sflags & 0xFFFFFFF1));
/* 279 */     if (parent != null) {
/* 280 */       parent.dirtyMessage(this, -1);
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */   String getFlags(ImapFolder i4folder)
/*     */   {
/* 287 */     if (((this.flags & IMAP_FLAGS) == Flag.BITMASK_UNREAD) && (ArrayUtil.isEmpty(this.tags)) && (this.sflags == 0)) {
/* 288 */       return "FLAGS ()";
/*     */     }
/*     */     
/* 291 */     StringBuilder result = new StringBuilder("FLAGS (");
/* 292 */     int empty = result.length();
/*     */     
/* 294 */     if ((this.flags & Flag.BITMASK_DELETED) != 0) {
/* 295 */       result.append(result.length() == empty ? "" : " ").append("\\Deleted");
/*     */     }
/* 297 */     if ((this.flags & Flag.BITMASK_DRAFT) != 0) {
/* 298 */       result.append(result.length() == empty ? "" : " ").append("\\Draft");
/*     */     }
/* 300 */     if ((this.flags & Flag.BITMASK_FLAGGED) != 0) {
/* 301 */       result.append(result.length() == empty ? "" : " ").append("\\Flagged");
/*     */     }
/* 303 */     if ((this.flags & Flag.BITMASK_REPLIED) != 0) {
/* 304 */       result.append(result.length() == empty ? "" : " ").append("\\Answered");
/*     */     }
/* 306 */     if ((this.flags & Flag.BITMASK_NOTIFIED) != 0) {
/* 307 */       result.append(result.length() == empty ? "" : " ").append("$MDNSent");
/*     */     }
/* 309 */     if ((this.flags & Flag.BITMASK_FORWARDED) != 0) {
/* 310 */       result.append(result.length() == empty ? "" : " ").append("$Forwarded Forwarded");
/*     */     }
/*     */     
/* 313 */     if ((this.flags & Flag.BITMASK_UNREAD) == 0) {
/* 314 */       result.append(result.length() == empty ? "" : " ").append("\\Seen");
/*     */     }
/*     */     
/* 317 */     if ((this.sflags & 0x1) != 0) {
/* 318 */       result.append(result.length() == empty ? "" : " ").append("\\Recent");
/*     */     }
/* 320 */     if ((this.sflags & 0x2) != 0) {
/* 321 */       result.append(result.length() == empty ? "" : " ").append("$Junk Junk");
/*     */     }
/* 323 */     if ((this.sflags & 0x4) != 0) {
/* 324 */       result.append(result.length() == empty ? "" : " ").append("$NotJunk NotJunk NonJunk");
/*     */     }
/* 326 */     if ((this.sflags & 0x8) != 0) {
/* 327 */       result.append(result.length() == empty ? "" : " ").append("JunkRecorded");
/*     */     }
/*     */     
/* 330 */     ImapFlagCache i4cache = i4folder.getTagset();
/* 331 */     if (!ArrayUtil.isEmpty(this.tags)) {
/* 332 */       for (String tag : this.tags) {
/* 333 */         ImapFlagCache.ImapFlag i4flag = i4cache.getByZimbraName(tag);
/* 334 */         if (i4flag != null)
/*     */         {
/* 336 */           ImapFlagCache.ImapFlag other = i4folder.getFlagByName(i4flag.mImapName);
/* 337 */           if ((other == null) || (other == i4flag)) {
/* 338 */             result.append(result.length() == empty ? "" : " ").append(i4flag);
/*     */           }
/*     */         }
/*     */       }
/*     */     }
/*     */     
/* 344 */     return ')';
/*     */   }
/*     */   
/* 347 */   private static final byte[] NIL = { 78, 73, 76 };
/*     */   
/*     */   private static void nstring(PrintStream ps, String value) {
/* 350 */     if (value == null) {
/* 351 */       ps.write(NIL, 0, 3);
/*     */     } else {
/* 353 */       astring(ps, value, false);
/*     */     }
/*     */   }
/*     */   
/*     */   private static void astring(PrintStream ps, String value) {
/* 358 */     if (value == null) {
/* 359 */       ps.print("\"\"");
/*     */     } else {
/* 361 */       astring(ps, value, false);
/*     */     }
/*     */   }
/*     */   
/*     */   private static void aSTRING(PrintStream ps, String value) {
/* 366 */     if (value == null) {
/* 367 */       ps.print("\"\"");
/*     */     } else {
/* 369 */       astring(ps, value, true);
/*     */     }
/*     */   }
/*     */   
/*     */   private static void astring(PrintStream ps, String value, boolean upcase) {
/* 374 */     boolean literal = false;
/* 375 */     StringBuilder nonulls = null;
/* 376 */     int i = 0;int lastNull = -1;
/* 377 */     for (int length = value.length(); i < length; i++) {
/* 378 */       char c = value.charAt(i);
/* 379 */       if (c == 0) {
/* 380 */         if (nonulls == null) {
/* 381 */           nonulls = new StringBuilder();
/*     */         }
/* 383 */         nonulls.append(value.substring(lastNull + 1, i));
/* 384 */         lastNull = i;
/* 385 */       } else if ((c == '"') || (c == '\\') || (c >= '') || (c < ' ')) {
/* 386 */         literal = true;
/*     */       }
/*     */     }
/*     */     
/* 390 */     String content = value.substring(lastNull + 1, i);
/* 391 */     if (upcase) {
/* 392 */       content = content.toUpperCase();
/*     */     }
/*     */     
/* 395 */     if (!literal) {
/* 396 */       ps.write(34);ps.print(content);ps.write(34);
/*     */     } else {
/*     */       try {
/* 399 */         byte[] bytes = content.getBytes("utf-8");
/* 400 */         ps.write(123);ps.print(bytes.length);ps.write(125);
/* 401 */         ps.write(ImapHandler.LINE_SEPARATOR_BYTES, 0, 2);
/* 402 */         ps.write(bytes, 0, bytes.length);
/*     */       } catch (UnsupportedEncodingException uee) {
/* 404 */         ps.write(NIL, 0, 3);
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   private static void nstring2047(PrintStream ps, String value) {
/* 410 */     if (value == null) {
/* 411 */       ps.write(NIL, 0, 3);return;
/*     */     }
/*     */     
/* 414 */     boolean encoded = false;
/* 415 */     int i = 0; for (int length = value.length(); i < length; i++) {
/* 416 */       char c = value.charAt(i);
/* 417 */       if ((c == '"') || (c == '\\') || (c >= '') || (c < ' ')) {
/* 418 */         encoded = true;
/*     */       }
/*     */     }
/* 421 */     if (!encoded) {
/* 422 */       ps.write(34);ps.print(value);ps.write(34);
/*     */     }
/*     */     else {
/*     */       try {
/* 426 */         ps.write(34);ps.print(new BCodec().encode(value, "utf-8"));ps.write(34);
/*     */       } catch (EncoderException ee) {
/* 428 */         ps.write(NIL, 0, 3);
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   private static void address(PrintStream ps, InternetAddress addr) {
/* 434 */     String address = addr.getAddress().trim();String route = null;
/*     */     
/*     */     int colon;
/*     */     
/* 438 */     if ((address.startsWith("@")) && ((colon = address.indexOf(':')) != -1)) {
/* 439 */       route = address.substring(0, colon);
/* 440 */       address = address.substring(colon + 1);
/*     */     }
/*     */     
/* 443 */     String[] parts = address.split("@", 2);
/* 444 */     ps.write(40);nstring2047(ps, addr.getPersonal());
/* 445 */     ps.write(32);nstring(ps, route);
/* 446 */     ps.write(32);nstring(ps, parts[0]);
/* 447 */     ps.write(32);nstring(ps, parts.length > 1 ? parts[1] : null);
/* 448 */     ps.write(41);
/*     */   }
/*     */   
/*     */   private static void naddresses(PrintStream ps, InternetAddress[] addrs) {
/* 452 */     int count = 0;
/* 453 */     if ((addrs != null) && (addrs.length > 0)) {
/* 454 */       for (InternetAddress addr : addrs) {
/* 455 */         if (addr.isGroup())
/*     */         {
/*     */ 
/*     */ 
/*     */           try
/*     */           {
/*     */ 
/* 462 */             String serialized = addr.getAddress();
/* 463 */             int colon = serialized.indexOf(':');
/* 464 */             String name = colon == -1 ? serialized : serialized.substring(0, colon);
/* 465 */             InternetAddress[] members = addr.getGroup(false);
/*     */             
/* 467 */             if (count++ == 0) {
/* 468 */               ps.write(40);
/*     */             }
/* 470 */             ps.print("(NIL NIL ");nstring(ps, name);ps.print(" NIL)");
/* 471 */             if (members != null) {
/* 472 */               for (InternetAddress member : members) {
/* 473 */                 address(ps, member);
/*     */               }
/*     */             }
/* 476 */             ps.print("(NIL NIL NIL NIL)");
/*     */           } catch (ParseException e) {}
/* 478 */         } else if (addr.getAddress() != null)
/*     */         {
/*     */ 
/*     */ 
/*     */ 
/* 483 */           if (count++ == 0) {
/* 484 */             ps.write(40);
/*     */           }
/* 486 */           address(ps, addr);
/*     */         }
/*     */       }
/*     */     }
/*     */     
/* 491 */     if (count == 0) {
/* 492 */       ps.write(NIL, 0, 3);
/*     */     } else {
/* 494 */       ps.write(41);
/*     */     }
/*     */   }
/*     */   
/*     */   private static void nlist(PrintStream ps, String[] list) {
/* 499 */     if ((list == null) || (list.length == 0)) {
/* 500 */       ps.print("NIL");
/* 501 */     } else if (list.length == 1) {
/* 502 */       astring(ps, list[0]);
/*     */     } else {
/* 504 */       ps.write(40);
/* 505 */       for (int i = 0; i < list.length; i++) {
/* 506 */         if (i != 0) {
/* 507 */           ps.write(32);
/*     */         }
/* 509 */         astring(ps, list[i]);
/*     */       }
/* 511 */       ps.write(41);
/*     */     }
/*     */   }
/*     */   
/*     */   private static void nparams(PrintStream ps, MimeCompoundHeader header) {
/* 516 */     boolean first = true;
/* 517 */     for (Iterator<Map.Entry<String, String>> it = header.parameterIterator(); it.hasNext(); first = false) {
/* 518 */       Map.Entry<String, String> param = (Map.Entry)it.next();
/* 519 */       ps.print(first ? '(' : ' ');aSTRING(ps, (String)param.getKey());ps.write(32);nstring2047(ps, (String)param.getValue());
/*     */     }
/* 521 */     ps.print(first ? "NIL" : ")");
/*     */   }
/*     */   
/*     */   private static void ndisposition(PrintStream ps, String disposition) {
/* 525 */     if (disposition == null) {
/* 526 */       ps.print("NIL");
/*     */     } else {
/* 528 */       ContentDisposition cdisp = new ContentDisposition(disposition);
/* 529 */       ps.write(40);astring(ps, cdisp.getDisposition());
/* 530 */       ps.write(32);nparams(ps, cdisp);
/* 531 */       ps.write(41);
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   static void serializeEnvelope(PrintStream ps, MimeMessage mm)
/*     */     throws MessagingException
/*     */   {
/* 540 */     InternetAddress[] from = Mime.parseAddressHeader(mm, "From", false);
/* 541 */     InternetAddress[] sender = Mime.parseAddressHeader(mm, "Sender", false);InternetAddress[] replyTo = Mime.parseAddressHeader(mm, "Reply-To", false);
/* 542 */     ps.write(40);nstring(ps, mm.getHeader("Date", ","));
/* 543 */     ps.write(32);nstring2047(ps, Mime.getSubject(mm));
/* 544 */     ps.write(32);naddresses(ps, from);
/* 545 */     ps.write(32);naddresses(ps, sender.length == 0 ? from : sender);
/* 546 */     ps.write(32);naddresses(ps, replyTo.length == 0 ? from : replyTo);
/* 547 */     ps.write(32);naddresses(ps, Mime.parseAddressHeader(mm, "To", false));
/* 548 */     ps.write(32);naddresses(ps, Mime.parseAddressHeader(mm, "CC", false));
/* 549 */     ps.write(32);naddresses(ps, Mime.parseAddressHeader(mm, "BCC", false));
/* 550 */     ps.write(32);nstring(ps, mm.getHeader("In-Reply-To", " "));
/* 551 */     ps.write(32);nstring(ps, mm.getMessageID());
/* 552 */     ps.write(41);
/*     */   }
/*     */   
/* 555 */   private static String nATOM(String value) { return '"' + value.toUpperCase() + '"'; }
/*     */   
/*     */   static void serializeStructure(PrintStream ps, MimeMessage root, boolean extensions) throws IOException, MessagingException {
/* 558 */     LinkedList<LinkedList<MPartInfo>> queue = new LinkedList();
/* 559 */     LinkedList<MPartInfo> level = new LinkedList();
/* 560 */     level.add(Mime.getParts(root).get(0));
/* 561 */     queue.add(level);
/*     */     
/* 563 */     boolean pop = false;
/* 564 */     while (!queue.isEmpty()) {
/* 565 */       level = (LinkedList)queue.getLast();
/* 566 */       if (level.isEmpty()) {
/* 567 */         queue.removeLast();
/* 568 */         pop = true;
/*     */       }
/*     */       else
/*     */       {
/* 572 */         MPartInfo mpi = (MPartInfo)level.getFirst();
/* 573 */         MimePart mp = mpi.getMimePart();
/* 574 */         boolean hasChildren = (mpi.getChildren() != null) && (!mpi.getChildren().isEmpty());
/*     */         
/*     */ 
/* 577 */         ContentType ctype = new ContentType(mp.getHeader("Content-Type", null)).setContentType(mpi.getContentType());
/* 578 */         String primary = nATOM(ctype.getPrimaryType());String subtype = nATOM(ctype.getSubType());
/*     */         
/* 580 */         if (!pop)
/* 581 */           ps.write(40);
/* 582 */         if (primary.equals("\"MULTIPART\"")) {
/* 583 */           if (!pop)
/*     */           {
/*     */ 
/*     */ 
/*     */ 
/* 588 */             if (!hasChildren) {
/* 589 */               ps.print("NIL");
/*     */             } else {
/* 591 */               queue.addLast(new LinkedList(mpi.getChildren()));
/* 592 */               continue;
/*     */             }
/*     */           }
/* 595 */           ps.write(32);ps.print(subtype);
/* 596 */           if (extensions)
/*     */           {
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 603 */             ps.write(32);nparams(ps, ctype);
/* 604 */             ps.write(32);ndisposition(ps, mp.getHeader("Content-Disposition", null));
/* 605 */             ps.write(32);nlist(ps, mp.getContentLanguage());
/* 606 */             ps.write(32);nstring(ps, mp.getHeader("Content-Location", null));
/*     */           }
/*     */         } else {
/* 609 */           if (!pop)
/*     */           {
/*     */ 
/*     */ 
/* 613 */             String cte = mp.getEncoding();
/* 614 */             cte = (cte == null) || (cte.trim().equals("")) ? "7bit" : cte;
/* 615 */             aSTRING(ps, ctype.getPrimaryType());ps.write(32);aSTRING(ps, ctype.getSubType());
/* 616 */             ps.write(32);nparams(ps, ctype);
/* 617 */             ps.write(32);nstring(ps, mp.getContentID());
/* 618 */             ps.write(32);nstring2047(ps, mp.getDescription());
/* 619 */             ps.write(32);aSTRING(ps, cte);
/* 620 */             ps.write(32);ps.print(Math.max(mp.getSize(), 0));
/*     */           }
/* 622 */           boolean rfc822 = (primary.equals("\"MESSAGE\"")) && (subtype.equals("\"RFC822\""));
/* 623 */           if (rfc822)
/*     */           {
/*     */ 
/*     */ 
/* 627 */             if (!pop) {
/* 628 */               if (!hasChildren) {
/* 629 */                 ps.print(" NIL NIL");
/*     */               } else {
/* 631 */                 MimeMessage mm = (MimeMessage)((MPartInfo)mpi.getChildren().get(0)).getMimePart();
/* 632 */                 ps.write(32);serializeEnvelope(ps, mm);ps.write(32);
/* 633 */                 queue.addLast(new LinkedList(mpi.getChildren()));
/* 634 */                 continue;
/*     */               }
/*     */             }
/* 637 */             ps.write(32);ps.print(getLineCount(mp));
/* 638 */           } else if (primary.equals("\"TEXT\""))
/*     */           {
/*     */ 
/*     */ 
/* 642 */             ps.write(32);ps.print(getLineCount(mp));
/*     */           }
/* 644 */           if (extensions)
/*     */           {
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 651 */             ps.write(32);nstring(ps, mp.getContentMD5());
/* 652 */             ps.write(32);ndisposition(ps, mp.getHeader("Content-Disposition", null));
/* 653 */             ps.write(32);nlist(ps, mp.getContentLanguage());
/* 654 */             ps.write(32);nstring(ps, mp.getHeader("Content-Location", null));
/*     */           }
/*     */         }
/* 657 */         ps.write(41);
/*     */         
/* 659 */         level.removeFirst();
/* 660 */         pop = false;
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   private static int getLineCount(MimePart mp) {
/*     */     try {
/* 667 */       int lines = mp.getLineCount();
/* 668 */       if (lines > 0) {
/* 669 */         return lines;
/*     */       }
/*     */     }
/*     */     catch (MessagingException e) {}
/*     */     
/* 674 */     InputStream is = null;
/*     */     try {
/* 676 */       if ((mp instanceof MimeBodyPart)) {
/* 677 */         is = ((MimeBodyPart)mp).getRawInputStream();
/* 678 */       } else if ((mp instanceof MimeMessage)) {
/* 679 */         is = ((MimeMessage)mp).getRawInputStream();
/*     */       } else {
/* 681 */         return 0;
/*     */       }
/*     */       
/* 684 */       int lines = 0;
/* 685 */       boolean complete = false;
/* 686 */       while ((c = is.read()) != -1) {
/* 687 */         if ((complete = c == 10 ? 1 : 0) == 1) {
/* 688 */           lines++;
/*     */         }
/*     */       }
/* 691 */       return complete ? lines : lines + 1;
/*     */     } catch (MessagingException e) {
/* 693 */       return 0;
/*     */     } catch (IOException e) { int c;
/* 695 */       return 0;
/*     */     } finally {
/* 697 */       ByteUtil.closeStream(is);
/*     */     }
/*     */   }
/*     */   
/*     */   public String toString()
/*     */   {
/* 703 */     return Objects.toStringHelper("").add("m", this.msgId).add("u", this.imapUid).toString();
/*     */   }
/*     */   
/*     */ 
/*     */   public static void main(String[] args)
/*     */   {
/* 709 */     PrintStream ps = new PrintStream(System.out);
/* 710 */     ps.print(ImapHandler.LINE_SEPARATOR_BYTES);
/* 711 */     String[] samples = { null, "test", "т", "ha\nnd", "\"dog\"", "ca\"t", "\000fr\000og\000" };
/* 712 */     for (String s : samples) {
/* 713 */       nstring2047(ps, s);ps.write(32);nstring(ps, s);ps.write(32);astring(ps, s);ps.write(32);aSTRING(ps, s);ps.write(10);
/*     */     }
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/imap/ImapMessage.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */